 

package com.zdkj.auth.handler;

import com.zdkj.admin.api.dto.UserInfo;
import com.zdkj.admin.api.entity.SysLog;
import com.zdkj.admin.api.entity.SysUser;
import com.zdkj.admin.api.feign.RemoteUserService;
import com.zdkj.common.core.constant.CacheConstants;
import com.zdkj.common.core.constant.CommonConstants;
import com.zdkj.common.core.constant.SecurityConstants;
import com.zdkj.common.core.util.R;
import com.zdkj.common.log.event.SysLogEvent;
import com.zdkj.common.log.util.SysLogUtils;
import com.zdkj.common.security.handler.AbstractAuthenticationFailureEvenHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 权限认证失败处理
 * @author cui_com
 * @date 2018/10/8
 */
@Slf4j
@Component
public class PigxAuthenticationFailureEvenHandler extends AbstractAuthenticationFailureEvenHandler {

	@Autowired
	private RemoteUserService remoteUserService;

	@Autowired
	private CacheManager cacheManager;

	@Autowired
	private ApplicationEventPublisher publisher;

	/**
	 * 登录失败最大次数
	 */
	private static Integer MAX_FAIL_LOGIN_COUNT = 5;

	/**
	 * 处理登录失败方法
	 *
	 *
	 * <p>
	 *
	 * @param authenticationException 登录的authentication 对象
	 * @param authentication          登录的authenticationException 对象
	 * @param request                 请求
	 * @param response                响应
	 */
	@Override
	public void handle(AuthenticationException authenticationException, Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
		log.info("用户：{} 登录失败，异常：{}", authentication.getPrincipal(), authenticationException.getLocalizedMessage());

		String userName = authentication.getPrincipal().toString();

		Cache failCountCache = cacheManager.getCache(CacheConstants.LOGIN_FAIL_COUNT);
		if(failCountCache != null){
			int failCount = 1;
			if(failCountCache.get(userName) != null){
				failCount += (int) failCountCache.get(userName).get();
			}
			failCountCache.put(userName,failCount);
			log.info("用户: {} 登录失败次数: {}",userName,failCount);
			if(failCount >= MAX_FAIL_LOGIN_COUNT){
				Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
				if (cache != null && cache.get(userName) != null) {
					cache.evict(userName);
				}
				remoteUserService.lockUser(authentication.getPrincipal().toString(),
						SecurityConstants.FROM_IN);
			}
		}

		//save log
		SysLog sysLog = SysLogUtils.getLoginLog(authentication);
		sysLog.setType(CommonConstants.LOG_TYPE_FAIL);
		sysLog.setException(authenticationException.getLocalizedMessage());
		//登录失败，记录登录失败的用户名即可
		/*
		R<UserInfo> result = remoteUserService.info(userName, SecurityConstants.FROM_IN);
		UserInfo userInfo = result.getData();
		if(userInfo != null){
			//获取登录用户基本信息
			SysUser sysUser = userInfo.getSysUser();
			sysLog.setCreateByName(sysUser.getNikename());
		}*/
		publisher.publishEvent(new SysLogEvent(sysLog));
	}
}
